package common

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
)

// 实现一个map任务管理器 从input files中读取内容
// 将输出分成指定数量的中间文件
// 自定义分割标准
func DoMap(
	// 参数列表
	jobName string, // 任务名称
	mapTaskNumber int, // 当前map任务编号
	inFile string, // 输入文件
	nReduce int, // 当前map任务执行的reduce编号
	mapF func(line string) []KeyValue) {

	// 从输入文件inFile中读取内容
	f, err := os.Open(inFile)
	if err != nil {
		fmt.Println("error : ", err.Error())
	}

	defer f.Close()

	// 通过调用mapF对内容进行处理 分割任务输出
	// 将指定文件的内容解析为key-value
	var kvs []KeyValue
	rd := bufio.NewReader(f)
	for {
		line, err := rd.ReadString('\n')
		if err != nil || io.EOF == err {
			if line == "" {
				break
			}
		}

		tmp := mapF(strings.Trim(line, "\n"))
		if tmp != nil && len(tmp) != 0 {
			kvs = append(kvs, tmp...)
		}
	}

	// 生成一个编码对象
	// 每一个map任务生成nReduce个中间文件对象
	encoders := make([]*json.Encoder, nReduce)

	for i := 0; i < nReduce; i++ {
		// 生成中间文件的名称
		filename := GetReduceName(jobName, mapTaskNumber, i)
		f, err := os.Create(filename)
		if err != nil {
			fmt.Println("error : ", err.Error())
		}

		defer f.Close()

		encoders[i] = json.NewEncoder(f)
	}

	// 将kvs中的内容存入到前面生成的中间文件中去
	for _, v := range kvs {
		// 自定义规则对key值进行分类 哈希求余 存入中间文件
		// 以编号的哈希值对nReduce进行求余
		index := IHash(v.Key) % nReduce
		err = encoders[index].Encode(&v)
		if err != nil {
			fmt.Println("error : ", err.Error())
		}
	}
}
